import { useDebounceFn } from "ahooks";
import { useEffect, useRef, useState } from "react";
import { IDataItem, IHeader, IOffset } from "./types";
import { useUpdateEffect } from "./use";

export const useVirtualScorll = () => app => {
  const { run } = useDebounceFn(fn => fn(), { wait: 500 });

  let list: IDataItem[] = app.ctx.dataSource;

  const [offset, setOffset]: [IOffset, any] = useState({ x: 0, y: 0 });

  const [result, setResult] = useState({
    viewData: [],
    header: [],
    offset: { offsetX: 0, offsetY: 0 }
  });

  const containerRef = useRef(null);

  app.ctx.containerRef = containerRef;

  const getViewData = function aaa() {
    let viewInfo = app.ctx.viewInfo;

    let { itemWidth, itemHeight, header } = viewInfo;

    let x = ~~(offset.x / itemWidth);
    let y = ~~(offset.y / itemHeight);

    let offsetY = -offset.y % itemHeight;
    let offsetX = -offset.x % itemWidth;

    let viewData: IDataItem[][] = [];
    let viewHeader: IHeader[] = [];

    if (header) {
      app.ctx.viewHeader = viewHeader = getRowData(
        header,
        header,
        viewInfo.fixed,
        viewInfo.viewWidth * viewInfo.preRenderRatio,
        x
      );
    }

    let renderWidth = viewHeader.reduce((pre, cur) => cur.width + pre, 0);

    let viewHeight = viewInfo.viewHeight * viewInfo.preRenderRatio;

    let height = 0;

    for (let vY = 0; height < viewHeight; height += itemHeight, vY++) {
      if (!list[y + vY]) {
        // viewData[vY]=[]
        break;
      }
      if (vY < viewInfo.fixed) {
        // 为固定行预留
        viewData[vY] = getRowData(
          header,
          list[y + vY],
          viewInfo.fixed,
          viewInfo.viewWidth * viewInfo.preRenderRatio,
          x
        );
      } else {
        viewData[vY] = getRowData(
          header,
          list[y + vY],
          viewInfo.fixed,
          viewInfo.viewWidth * viewInfo.preRenderRatio,
          x
        );
      }
    }

    console.log(
      "%c 🥤 viewData: ",
      "font-size:20px;background-color: #2EAFB0;color:#fff;",
      viewData,
      viewHeader
    );

    console.log("renderWidth", viewHeader, renderWidth, viewData.length);
    setResult({ viewData, header: viewHeader, offset: { offsetX, offsetY } });
  };

  app.actions.getViewData = getViewData;

  // useEffect(() => {
  //   app.actions.clearScroll = () => containerRef.current?.scrollTo(0, 0);
  // }, [setOffset]);

  useEffect(() => {
    app.ctx.wrapperPropsStyle = {
      width: add(app.ctx?.viewInfo?.header, "width") || 500,
      height: (app.ctx?.viewInfo?.itemHeight || 50) * app.ctx?.viewInfo?.y
    };
  }, [app.ctx?.viewInfo?.header, app.ctx?.viewInfo?.itemHight]);

  useUpdateEffect(() => {
    getViewData();
  }, [offset, list, setResult]);

  /** 半格自动变成整格 */
  useEffect(() => {
    const automaticAlignment = () => {
      console.log(
        "%c 🍫 result.offset: ",
        "font-size:20px;background-color: #93C0A4;color:#fff;",
        app.ctx.shouldAutomaticAlignment,
        [result.offset.offsetX, result.offset.offsetY]
      );
      if (
        !app.ctx.mouseDown &&
        [result.offset.offsetX, result.offset.offsetY].some(i => i !== 0)
      ) {
        containerRef.current.scrollTop =
          containerRef.current.scrollTop + result.offset.offsetY;
        containerRef.current.scrollLeft =
          containerRef.current.scrollLeft + result.offset.offsetX;
      }
    };


    

    run(automaticAlignment);

    console.log(
      "%c 🍫 result.offset: ",
      "font-size:20px;background-color: #93C0A4;color:#fff;",
      result.offset
    );
  }, [result.offset, setOffset, run, app]);

  return {
    props: ctx => {
      let { itemHeight, viewWidth, viewHeight } = app.ctx.viewInfo || {};
      console.log(
        "%c 🥘 app.ctx: ",
        "font-size:20px;background-color: #E41A6A;color:#fff;",
        app.ctx
      );

      return {
        containerProps: {
          ref: (ele: any) => {
            containerRef.current = ele;
          },
          onMouseDown: () => {
            app.ctx.mouseDown = true;
          },
          onMouseUp: () => {
            app.ctx.mouseDown = false;
          },
          onScroll: (e: any) => {
            //    return
            let finalX = e.target.scrollWidth - viewWidth;
            let finalY = e.target.scrollHeight - viewHeight;

            let offset = {
              x: e.target.scrollLeft > finalX ? finalX : e.target.scrollLeft,
              y: e.target.scrollTop > finalY ? finalY : e.target.scrollTop
            };

            console.log(
              "debugger-1   e.target.scrollWidth ,finalX, offset.x",
              e.target.scrollWidth,
              finalX,
              offset.x,
              finalY,
              offset.y
            );
            if (e.target.scrollWidth > 80000) {
              debugger;
            }

            setOffset(offset);
          },
          style: {
            position: "relative",
            overflow: "auto",
            width: viewWidth,
            height: viewHeight
          }
        },
        wrapperProps: {
          style: app.ctx.wrapperPropsStyle || {}
        },
        tableProps: {
          position: "absolute",
          top: offset.y,
          left: offset.x
        },
        offset: {
          "--tableOffsetX": result.offset.offsetX + "px",
          "--tableOffsetY": result.offset.offsetY + "px"
        },
        data: {
          ...result,
          viewInfo: { itemHeight }
        }
      };
    }
  };
};

const add = (arr: any[], key: string) => {
  return arr?.reduce?.((acc: number, cur: any) => acc + cur[key], 0);
};

/**
 * @description 获取一行数据
 * @author hcluo
 * @date 06/12/2020
 * @param {*} fixedNum
 * @param {*} header
 * @param {*} fullRow
 * @param {*} viewWidth
 * @param {number} x
 * @return {*}
 */

function getRowData(
  header: any,
  fullRow: any,
  fixedNum: any,
  viewWidth: any,
  x: number
) {
  let width = 0,
    colNum = 0;
  let rowData: any = [];

  for (; colNum < fixedNum; width += header[colNum].width, colNum++)
    rowData[colNum] = fullRow[colNum];

  for (; width < viewWidth; width += header[x + colNum].width, colNum++) {
    if (!header[x + colNum]) {
      //   rowData[colNum] = {};
      break;
    }
    rowData[colNum] = fullRow[x + colNum];
  }

  return rowData;
}
